package com.cskaoyan.javase.recursion._0introduction;

/**
 * 递归的引入
 * 我们已经学习过方法，使用过方法了。
 * 方法体中是可以调用方法的，那么如果在方法体中调用方法自身呢？
 *
 * 特别的，在一个方法的方法体当中再次调用自身方法，
 * 就像故事里提到同样的故事一样,这种"套娃"的理念，
 * 我们把方法在运行时调用自身的情况，称之为递归，又叫做递归调用。
 *
 * 递归的使用:
 *      1.要想使用递归,首先需要在方法体中调用自身方法,这是必须的
 *          我们把方法体中调用自身方法的语句称之为"递归体"
 *          递归体对于递归而言是不可缺少的.
 *
 *      2.如果一个递归只有递归体,而不考虑递归结束的条件,那么一定会导致递归栈溢出,程序报错终止
 *          所以正常的递归不可或缺的一部分是递归终止的条件
 *          我们把递归终止的条件称之为"递归的出口"
 *          正常可以执行的递归,必须有"递归的出口"
 *
 *      3.递归有递归体,有递归出口就是绝对安全的吗?
 *          递归即便有出口也不是绝对安全的
 *          还需要考虑递归的次数(称之为"递归的深度")
 *          递归的深度如果仍然超出了栈内存的大小
 *          仍然会栈溢出
 *
 * 总之,以上,递归是很危险的,稍有不慎,就会栈溢出错误
 * 实际开发中,使用递归要谨慎考虑,不要滥用.
 * 如果有不用的方案,尽量不要用递归.
 *
 * @since 10:53
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Demo {
    public static void main(String[] args) {
        System.out.println(sum(14000));
        /*
            思考,分析,上述方法调用的结果是什么?
                sum(10) = 10 + sum(9);
                sum(9) = 9 + sum(8);
                sum(8) = 8 + sum(7);
                ...
           显然以上过程是停不下来的,因为没有停止的条件,会不断的,会不停的调用方法
           结果可能是:
                1.报错
                2.死循环
                3.电脑炸了 (这不可能)

            Method 'sum()' recurses infinitely, and can only end by throwing an exception
            通过运行代码发现,程序报错了,抛出了异常,程序终止程序
            StackOverflowError: 栈溢出错误,Error是比Exception异常更加严重的问题,但它们都属于异常
            为什么会栈溢出错误?栈溢出是什么栈溢出?
            方法不能的调用,不停的有方法的栈帧进(JVM)栈,但是没有方法出栈,没有方法执行完毕,最终导致栈内存溢出报错
         */
    }

    // 递归求和
    public static long sum(int num) {
        // 递归的出口
        if (num == 0) {
            return 0;
        }
        // 递归体
        return num + sum(num - 1);
    }
}
